/**
 * @file ble_fcs.h
 * @brief 蓝牙烽火通信服务（fiberhome communication server）
 * @author wangh (wanghuan3037@fiberhome.com)
 * @version 1.0
 * @date 2021-02-03
 * @copyright Copyright (c) 2021  烽火通信
 * @note 应用需要调用 BLE_FCS_DEF 进行蓝牙服务观察者注册 @ref NRF_SDH_BLE_OBSERVER
 * @code
 *      BLE_FCS_DEF(m_fcs, NRF_SDH_BLE_TOTAL_LINK_COUNT);
 * @endcode
 */
#ifndef __BLE_FCS_H
#define __BLE_FCS_H

#include <stdint.h>
#include <stdbool.h>
#include "sdk_config.h"
#include "ble.h"
#include "ble_srv_common.h"
#include "nrf_sdh_ble.h"
#include "ble_link_ctx_manager.h"

#ifdef __cplusplus
extern "C" {
#endif

/**@brief ble_fcs 实例宏定义.
 *
 * @param     _name            服务实例名称
 * @param[in] _fcs_max_clients 最大 fcs 客户端连接数量
 * @hideinitializer
 */
#define BLE_FCS_DEF(_name, _fcs_max_clients)                      \
    BLE_LINK_CTX_MANAGER_DEF(CONCAT_2(_name, _link_ctx_storage),  \
                             (_fcs_max_clients),                  \
                             sizeof(ble_fcs_client_context_t));   \
    static ble_fcs_t _name =                                      \
    {                                                             \
        .p_link_ctx_storage = &CONCAT_2(_name, _link_ctx_storage) \
    };                                                            \
    NRF_SDH_BLE_OBSERVER(_name ## _obs,                           \
                         BLE_FCS_BLE_OBSERVER_PRIO,               \
                         ble_fcs_on_ble_evt,                      \
                         &_name)

#define BLE_UUID_FCS_SERVICE 0x181C ///< fiberhome communication 服务UUID（基于SIG-UUID版）

#define OPCODE_LENGTH        1
#define HANDLE_LENGTH        2

/**@brief   Maximum length of data (in bytes) that can be transmitted to the peer by the Nordic UART service module. */
#if defined(NRF_SDH_BLE_GATT_MAX_MTU_SIZE) && (NRF_SDH_BLE_GATT_MAX_MTU_SIZE != 0)
    #define BLE_FCS_MAX_DATA_LEN (NRF_SDH_BLE_GATT_MAX_MTU_SIZE - OPCODE_LENGTH - HANDLE_LENGTH)
#else
    #define BLE_FCS_MAX_DATA_LEN (BLE_GATT_MTU_SIZE_DEFAULT - OPCODE_LENGTH - HANDLE_LENGTH)
    #warning NRF_SDH_BLE_GATT_MAX_MTU_SIZE is not defined.
#endif


/**@brief FCS 服务事件类型. */
typedef enum
{
    BLE_FCS_EVT_RX_DATA,        ///< 有数据接收
    BLE_FCS_EVT_TX_RDY,         ///< 发送就绪
    BLE_FCS_EVT_COMM_STARTED,   ///< 通知使能
    BLE_FCS_EVT_COMM_STOPPED,   ///< 通知禁止
} ble_fcs_evt_type_t;


/* 前置声明 ble_fcs_t type. */
typedef struct ble_fcs_s ble_fcs_t;


/**@brief FCS 服务接收事件数据结构体
 * @details 当 @ref BLE_FCS_EVT_RX_DATA 产生时该结构体提供事件传递
 */
typedef struct
{
    uint8_t const * p_data; /**< A pointer to the buffer with received data. */
    uint16_t        length; /**< Length of received data. */
} ble_fcs_evt_rx_data_t;


/**@brief FCS 服务客户端上下文结构体
 * @details 包含主机关联的上下文状态
 */
typedef struct
{
    bool is_notification_enabled;   ///< FCS 通信特征对端通知使能状态
} ble_fcs_client_context_t;


/**@brief FCS 服务事件结构体
 *
 * @details This structure is passed to an event coming from service.
 */
typedef struct
{
    ble_fcs_evt_type_t         type;        ///< 事件类型
    ble_fcs_t                * p_fcs;       ///< 服务实例指针
    uint16_t                   conn_handle; ///< 连接句柄
    ble_fcs_client_context_t * p_link_ctx;  ///< 连接上下文指针
    union
    {
        ble_fcs_evt_rx_data_t rx_data;      ///< 接收数据 @ref BLE_FCS_EVT_RX_DATA
    } params;
} ble_fcs_evt_t;


/**@brief FCS 服务事件处理函数类型 */
typedef void (* ble_fcs_data_handler_t) (ble_fcs_evt_t * p_evt);


/**@brief FCS 服务初始化结构体 */
typedef struct
{
    ble_fcs_data_handler_t data_handler;    ///< 接收数据事件处理函数
} ble_fcs_init_t;


/**@brief FCS 服务结构体
 * @details 包含服务关联的状态信息
 */
struct ble_fcs_s
{
    uint8_t                         uuid_type;          ///< 服务基础 UUID 类型
    uint16_t                        service_handle;     /**< Handle of Nordic UART Service (as provided by the SoftDevice). */
    ble_gatts_char_handles_t        dt_handles;         /**< Handles related to the DT characteristic (as provided by the SoftDevice). */
    blcm_link_ctx_storage_t * const p_link_ctx_storage; /**< Pointer to link context storage with handles of all current connections and its context. */
    ble_fcs_data_handler_t          data_handler;       /**< Event handler to be called for handling received data. */
};


/**@brief   Function for initializing the Nordic UART Service.
 *
 * @param[out] p_fcs      Nordic UART Service structure. This structure must be supplied
 *                        by the application. It is initialized by this function and will
 *                        later be used to identify this particular service instance.
 * @param[in] p_fcs_init  Information needed to initialize the service.
 *
 * @retval NRF_SUCCESS If the service was successfully initialized. Otherwise, an error code is returned.
 * @retval NRF_ERROR_NULL If either of the pointers p_fcs or p_fcs_init is NULL.
 */
uint32_t ble_fcs_init(ble_fcs_t * p_fcs, ble_fcs_init_t const * p_fcs_init);


/**@brief   Function for handling the Nordic UART Service's BLE events.
 *
 * @details The Nordic UART Service expects the application to call this function each time an
 * event is received from the SoftDevice. This function processes the event if it
 * is relevant and calls the Nordic UART Service event handler of the
 * application if necessary.
 *
 * @param[in] p_ble_evt     Event received from the SoftDevice.
 * @param[in] p_context     Nordic UART Service structure.
 */
void ble_fcs_on_ble_evt(ble_evt_t const * p_ble_evt, void * p_context);


/**@brief   Function for sending a data to the peer.
 *
 * @details This function sends the input string as an RX characteristic notification to the
 *          peer.
 *
 * @param[in]     p_fcs       Pointer to the Nordic UART Service structure.
 * @param[in]     p_data      String to be sent.
 * @param[in,out] p_length    Pointer Length of the string. Amount of sent bytes.
 * @param[in]     conn_handle Connection Handle of the destination client.
 *
 * @retval NRF_SUCCESS If the string was sent successfully. Otherwise, an error code is returned.
 */
uint32_t ble_fcs_data_send(ble_fcs_t * p_fcs,
                           uint8_t   * p_data,
                           uint16_t  * p_length,
                           uint16_t    conn_handle);


#ifdef __cplusplus
}
#endif

#endif	 // __BLE_FCS_H 

/*********** (C) COPYRIGHT 2021 FiberHome *****END OF FILE****/
